/*     ----------------------------------------------------------------
*  @brief this file contains a function to read two line element sets. while
*    not formerly part of the sgp4 mathematical theory, it is
*    required for practical implemenation.
*   @author david vallado
*                               sgp4io.cpp
*
*    this file contains a function to read two line element sets. while 
*    not formerly part of the sgp4 mathematical theory, it is 
*    required for practical implemenation.
*
*                            companion code for
*               fundamentals of astrodynamics and applications
*                                    2007
*                              by david vallado
*
*       (w) 719-573-2600, email dvallado@agi.com
*
*    current :
*               3 sep 08  david vallado
*                           add operationmode for afspc (a) or improved (i)
*    changes :
*               9 may 07  david vallado
*                           fix year correction to 57
*              27 mar 07  david vallado
*                           misc fixes to manual inputs
*              14 aug 06  david vallado
*                           original baseline
*       ----------------------------------------------------------------      */

#include "sgp4io.h"
#include "sgp4_math.h"    // for several misc routines
#include "sgp4_date.h"

/* -----------------------------------------------------------------------------
**    @brief  this function converts the two line element set character string data to
*    variables and initializes the sgp4 variables
*     @param  longstr1    - first line of the tle
*     @param  longstr2    - second line of the tle
*     @param  typerun     - type of run
*     @param  typeinput   - type of manual input           mfe 'm', epoch 'e', dayofyr 'd'
*     @param  opsmode     - mode of operation afspc or improved 'a', 'i'
*     @param  whichconst  - which set of constants to use  72, 84
*     @param  satrec      outputs- structure containing all the sgp4 satellite information*
*     @author  david vallado
*
*                           function twoline2rv
*
*  this function converts the two line element set character string data to
*    variables and initializes the sgp4 variables. several intermediate varaibles
*    and quantities are determined. note that the result is a structure so multiple
*    satellites can be processed simultaneously without having to reinitialize. the
*    verification mode is an important option that permits quick checks of any
*    changes to the underlying technical theory. this option works using a
*    modified tle file in which the start, stop, and delta time values are
*    included at the end of the second line of data. this only works with the
*    verification mode. the catalog mode simply propagates from -1440 to 1440 min
*    from epoch and is useful when performing entire catalog runs.
*
*  author        : david vallado                  719-573-2600    1 mar 2001
*
*  inputs        :
*    longstr1    - first line of the tle
*    longstr2    - second line of the tle
*    typerun     - type of run                    verification 'v', catalog 'c', 
*                                                 manual 'm'
*    typeinput   - type of manual input           mfe 'm', epoch 'e', dayofyr 'd'
*    opsmode     - mode of operation afspc or improved 'a', 'i'
*    whichconst  - which set of constants to use  72, 84
*
*  outputs       :
*    satrec      - structure containing all the sgp4 satellite information
*
*  coupling      :
*    getgravconst-
*    days2mdhms  - conversion of days to month, day, hour, minute, second
*    jday        - convert day month year hour minute second into julian date
*    sgp4init    - initialize the sgp4 variables
*
*  references    :
*    norad spacetrack report #3
*    vallado, crawford, hujsak, kelso  2006
*
*
  --------------------------------------------------------------------------- */
/**
 * @brief Esta función convierte el conjunto de datos de carácteres String two line element en variables e inicializa las variables de sgp4
 * @param longstr1 La primera linea de two line elements
 * @param longstr2 Segunda linea de two line elements
 * @param typerun Tipo de ejecución. 'v' para verificación, 'c' para catálogo y 'm' para manual.
 * @param typeinput Tipo de entrada individual. 'm' para mfe, 'e' para epoca, 'd' para día del año.
 * @param opsmode Tipo de operación. 'a' para afspc, 'i' para mejora.
 * @param whichconst Tipo de conjunto de constantes parara usar
 * @param satrec Estructura que contiene toda la información del satélite de sgp4.
 * @return *Sgp4unit Objeto sgp4unit inicializado.
 */
Sgp4unit*  Sgp4io::twoline2rv(
      char      longstr1[130], char longstr2[130],
      char      typerun,  char typeinput, char opsmode,
      gravconsttype       whichconst,
      double& startmfe, double& stopmfe, double& deltamin)
     {
       const double deg2rad  =   pi / 180.0;         //   0.0174532925199433
       const double xpdotp   =  1440.0 / (2.0 *pi);  // 229.1831180523293

       double sec, mu, radiusearthkm, tumin, xke, j2, j3, j4, j3oj2;
       double startsec, stopsec, startdayofyr, stopdayofyr, jdstart, jdstop;
       int startyear, stopyear, startmon, stopmon, startday, stopday,
           starthr, stophr, startmin, stopmin;
       int cardnumb, numb, j;
       long revnum = 0, elnum = 0;
       char classification, intldesg[11];
       int year = 0;
       int mon, day, hr, minute, nexp, ibexp;

       Sgp4unit* sgp4 =new Sgp4unit();
       elsetrec* satrec=sgp4->getSatrec();
       long int satsum=satsum;
       int epochyr=sgp4->getSatrec()->getEpochyr();

       double epochdays=sgp4->getSatrec()->getEpochdays();
       double ndot=sgp4->getSatrec()->getNdot();
       double nddot=sgp4->getSatrec()->getNddot();
       double bstar=sgp4->getSatrec()->getBstar();

       double inclo=sgp4->getSatrec()->getInclo();
	   double nodeo=sgp4->getSatrec()->getNodeo();
	   double ecco=sgp4->getSatrec()->getEcco();
	   double argpo=sgp4->getSatrec()->getArgpo();
	   double mo=sgp4->getSatrec()->getMo();
	   double no=sgp4->getSatrec()->getNo();


       getgravconst( whichconst, tumin, mu, radiusearthkm, xke, j2, j3, j4, j3oj2 );

       sgp4->getSatrec()->setError(0);

       // set the implied decimal points since doing a formated read
       // fixes for bad input data values (missing, ...)
       for (j = 10; j <= 15; j++)
           if (longstr1[j] == ' ')
               longstr1[j] = '_';

       if (longstr1[44] != ' ')
           longstr1[43] = longstr1[44];
       longstr1[44] = '.';
       if (longstr1[7] == ' ')
           longstr1[7] = 'U';
       if (longstr1[9] == ' ')
           longstr1[9] = '.';
       for (j = 45; j <= 49; j++)
           if (longstr1[j] == ' ')
               longstr1[j] = '0';
       if (longstr1[51] == ' ')
           longstr1[51] = '0';
       if (longstr1[53] != ' ')
           longstr1[52] = longstr1[53];
       longstr1[53] = '.';
       longstr2[25] = '.';
       for (j = 26; j <= 32; j++)
           if (longstr2[j] == ' ')
               longstr2[j] = '0';
       if (longstr1[62] == ' ')
           longstr1[62] = '0';
       if (longstr1[68] == ' ')
           longstr1[68] = '0';





       sscanf(longstr1,"%2d %5ld %1c %10s %2d %12lf %11lf %7lf %2d %7lf %2d %2d %6ld ",
    		   &cardnumb,&satsum,&classification, intldesg,&epochyr,
               &epochdays,&ndot,&nddot, &nexp,&bstar,
               &ibexp, &numb, &elnum );

       if (typerun == 'v')  // run for specified times from the file
         {
           if (longstr2[52] == ' ')
               sscanf(longstr2,"%2d %5ld %9lf %9lf %8lf %9lf %9lf %10lf %6ld %lf %lf %lf \n",
                       &cardnumb,&satsum,&inclo,
                       &nodeo,&ecco, &argpo, &mo,&no,
                       &revnum, &startmfe, &stopmfe, &deltamin );
             else
               sscanf(longstr2,"%2d %5ld %9lf %9lf %8lf %9lf %9lf %11lf %6ld %lf %lf %lf \n",
                       &cardnumb,&satsum,&inclo,
                       &nodeo,&ecco, &argpo,&mo, &no,
                       &revnum, &startmfe, &stopmfe, &deltamin );
         }
         else  // simply run -1 day to +1 day or user input times
         {
           if (longstr2[52] == ' ')
               sscanf(longstr2,"%2d %5ld %9lf %9lf %8lf %9lf %9lf %10lf %6ld \n",
                       &cardnumb,&satsum,&inclo,
                       &nodeo,&ecco, &argpo,&mo,&no,
                       &revnum );
             else
               sscanf(longstr2,"%2d %5ld %9lf %9lf %8lf %9lf %9lf %11lf %6ld \n",
                       &cardnumb,&satsum, &inclo,
                       &nodeo,&ecco, &argpo, &mo, &no,
                       &revnum );
         }
       satrec->setSatnum(satsum);
       satrec->setEpochdays(epochdays);
       satrec->setEpochyr(epochyr);
       satrec->setNdot(ndot);
       satrec->setNddot(nddot);
       satrec->setBstar(bstar);
       satrec->setInclo(inclo);
       satrec->setNodeo(nodeo);
       satrec->setEcco(ecco);
       satrec->setArgpo(argpo);
       satrec->setMo(mo);
       satrec->setNo(no);




       // ---- find no, ndot, nddot ----
       satrec->setNo(satrec->getNo() / xpdotp); //* rad/min
       satrec->setNddot(satrec->getNddot() * pow(10.0, nexp));
       satrec->setBstar(satrec->getBstar() * pow(10.0, ibexp));

       // ---- convert to sgp4 units ----
       satrec->setA    ( pow( satrec->getNo()*tumin , (-2.0/3.0) ));
       satrec->setNdot ( satrec->getNdot()  / (xpdotp*1440.0));  //* ? * minperday
       satrec->setNddot( satrec->getNddot() / (xpdotp*1440.0*1440));

       // ---- find standard orbital elements ----
       satrec->setInclo( satrec->getInclo()  * deg2rad);
       satrec->setNodeo( satrec->getNodeo()  * deg2rad);
       satrec->setArgpo( satrec->getArgpo()  * deg2rad);
       satrec->setMo    (satrec->getMo()     * deg2rad);

       satrec->setAlta ( satrec->getA()*(1.0 + satrec->getEcco()) - 1.0);
       satrec->setAltp ( satrec->getA()*(1.0 - satrec->getEcco()) - 1.0);

       // ----------------------------------------------------------------
       // find sgp4epoch time of element set
       // remember that sgp4 uses units of days from 0 jan 1950 (sgp4epoch)
       // and minutes from the epoch (time)
       // ----------------------------------------------------------------

       // ---------------- temp fix for years from 1957-2056 -------------------
       // --------- correct fix will occur when year is 4-digit in tle ---------
       if (satrec->getEpochyr() < 57)
           year= satrec->getEpochyr() + 2000;
         else
           year= satrec->getEpochyr() + 1900;
            sgp4_date::days2mdhms ( year,satrec->getEpochdays(), mon,day,hr,minute,sec );
           double jd2=0;
           sgp4_date::jday( year,mon,day,hr,minute,sec,jd2);

           satrec->setJdsatepoch(jd2);

       // ---- input start stop times manually
       if ((typerun != 'v') && (typerun != 'c'))
         {
         // ------------- enter start/stop ymd hms values --------------------
           if (typeinput == 'e')
             {
               printf("input start prop year mon day hr min sec \n");
               // make sure there is no space at the end of the format specifiers in scanf!
               scanf( "%i %i %i %i %i %lf",&startyear, &startmon, &startday, &starthr, &startmin, &startsec);
               fflush(stdin);
               sgp4_date::jday( startyear,startmon,startday,starthr,startmin,startsec, jdstart );

               printf("input stop prop year mon day hr min sec \n");
               scanf( "%i %i %i %i %i %lf",&stopyear, &stopmon, &stopday, &stophr, &stopmin, &stopsec);
               fflush(stdin);
               sgp4_date::jday( stopyear,stopmon,stopday,stophr,stopmin,stopsec, jdstop );

               startmfe = (jdstart - satrec->getJdsatepoch()) * 1440.0;
               stopmfe  = (jdstop - satrec->getJdsatepoch()) * 1440.0;

               printf("input time step in minutes \n");
               scanf( "%lf",&deltamin );
             }
           // -------- enter start/stop year and days of year values -----------
           if (typeinput == 'd')
             {
               printf("input start year dayofyr \n");
               scanf( "%i %lf",&startyear, &startdayofyr );
               printf("input stop year dayofyr \n");
               scanf( "%i %lf",&stopyear, &stopdayofyr );

                sgp4_date::days2mdhms ( startyear,startdayofyr, mon,day,hr,minute,sec );
               sgp4_date::jday( startyear,mon,day,hr,minute,sec, jdstart );
                sgp4_date::days2mdhms ( stopyear,stopdayofyr, mon,day,hr,minute,sec );
                sgp4_date::jday( stopyear,mon,day,hr,minute,sec, jdstop );

               startmfe = (jdstart - satrec->getJdsatepoch()) * 1440.0;
               stopmfe  = (jdstop - satrec->getJdsatepoch()) * 1440.0;

               printf("input time step in minutes \n");
               scanf( "%lf",&deltamin );
             }
           // ------------------ enter start/stop mfe values -------------------
           if (typeinput == 'm')
             {
               printf("input start min from epoch \n");
               scanf( "%lf",&startmfe );
               printf("input stop min from epoch \n");
               scanf( "%lf",&stopmfe );
               printf("input time step in minutes \n");
               scanf( "%lf",&deltamin );
             }
         }

       // ------------ perform complete catalog evaluation, -+ 1 day ----------- 
       if (typerun == 'c')
         {
           startmfe = -1440.0;
           stopmfe  =  1440.0;
           deltamin =    10.0;
         }

       // ---------------- initialize the orbit at sgp4epoch -------------------
      sgp4->sgp4init( whichconst, opsmode);
      return sgp4;
    } // end twoline2rv


